#include "SonyDecoder.h"


SonyDecoder::SonyDecoder( ILoggerPtr logger, PublisherPtr publisher ) : BaseIrDecoder(logger, publisher)
{

}

bool SonyDecoder::process ( unsigned long * Data, size_t DataCount )
{
	DWORD i;

    if (!Data)
    {
        m_DetectState = DETECT_HEADER_PULSE;
        return false;
    }

    for (i = 0 ; i < DataCount ; i++)
    {
        DWORD Duration = Data[i] & PULSE_MASK;
        BOOL Pulse = ((Data[i] & PULSE_BIT) != 0);
        BOOL Ignored = TRUE;
        switch(m_DetectState)
        {
        case DETECT_HEADER_PULSE:
            if (Pulse && (Duration >= 2100) && (Duration <= 2700))
            {
                m_DetectState = DETECT_HEADER_SPACE;
                Ignored = FALSE;                
            }
            break;
        case DETECT_HEADER_SPACE:
            if (!Pulse && (Duration >= 500) && (Duration <= 700))
            {
                m_DetectState = DETECT_DATA;
                Ignored = FALSE;
                m_HalfBit = 0;
                m_Bit = 0;
                m_Code = 0;                
            }
            break;
        case DETECT_DATA:
            if ((m_HalfBit % 2) == 0)
            {
                if (!Pulse) break;

                if ((Duration >= 400) && (Duration <= 750))
                {
                    Ignored = FALSE;
                    m_HalfBit = 1;
                    m_Bit++;                    
                }
                else if ((Duration >= 1000) && (Duration <= 1300))
                {
                    Ignored = FALSE;
                    m_HalfBit = 1;
                    m_Code |= 1 << m_Bit++;
                }
                else
                {					
					//  DebugSONY("Pulse error %d on bit %d\n", Duration, m_Bit);
                }
                break;
            }
            else
            {
                if (Pulse) 
                    break;

                if ((Duration >= 400) && (Duration <= 750))
                {
                    Ignored = FALSE;
                    m_HalfBit = 0;                    
                }
                else if ((Duration > 8000) &&
                    (m_Bit == 8) || (m_Bit == 12) || (m_Bit == 15) || (m_Bit == 20))
                {
                    Ignored = FALSE;
                    m_DetectState = DETECT_KEYCODE;
                    i--;                    
                }
                else
                {
                    // DebugSONY("Space error %d on bit %d\n", Duration, m_Bit);
                }
            }
            break;
        }
        if (m_DetectState == DETECT_KEYCODE)
        {
            BOOL IsValid = FALSE;
            if (m_LastCode != m_Code)
            {
                IsValid = TRUE;
                m_LastCode = m_Code;
                m_LastTime = GetTickCount();
                m_RepeatCount = 0;
            }
			else
			{
				DWORD cur = GetTickCount();
				IsValid = TRUE;
				
				if (( m_RepeatCount == 0 ) && (cur - m_LastTime  < m_KbdFirstRepeat ))
				{
					
					m_RepeatCount++;
				}
				else if (( m_RepeatCount > 0 ) && ( cur - m_LastTime < m_KbdNextRepeats ))
				{					
					m_RepeatCount++;
				}
				else
				{
					// too slow.
					m_RepeatCount = 0;
				}

				m_LastTime = cur;
	
			}

            m_DetectState = DETECT_HEADER_PULSE;

            if (IsValid)
            {
                m_Code &= 0x0000FFFF;                
				m_Publisher->call( ID_SONY_KEYCODE, m_Code, m_RepeatCount,"?");
				return true;
            }
        }
        if (Ignored && (m_DetectState != DETECT_HEADER_PULSE))
        {
            m_DetectState = DETECT_HEADER_PULSE;            
        }
    }
	return false;
}
